package in.muton.edushare.pages.batch;

import in.muton.edushare.documentModel.excel.ExcelUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.Loop;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;

import com.edushare.common.vo.FilesUploaded;

public abstract class ExcelFormDisplayPanel extends Panel {

	private static final long serialVersionUID = 4700535457233568266L;
	private List<String[]> fields;
	private String[] colTitles;

	public ExcelFormDisplayPanel(String id,
			IModel<FilesUploaded> fileUploadedModel, int columns,
			int startingRowIndex) throws InvalidFormatException, IOException {
		this(id, fileUploadedModel, columns, startingRowIndex, null);
	}

	public ExcelFormDisplayPanel(String id,
			IModel<FilesUploaded> fileUploadedModel, int columns,
			int startingRowIndex, String[] columnTitle)
			throws InvalidFormatException, IOException {
		super(id);
		// -2. Validate the data
		if (columns < 1 || startingRowIndex < 0)
			throw new IllegalStateException(
					"Columns to be read can't be less than 1 and Starting Row Index can't be less than 0");

		// -1. Create column header title if not provided
		if (columnTitle == null || columnTitle.length < 1) {
			this.colTitles = createColumnTitle(columns);
		} else if (columnTitle.length < columns) {
			this.colTitles = createColumnTitle(columnTitle, columns);
		} else {
			this.colTitles = columnTitle;
		}

		// 0. Read the file from path
		String path = fileUploadedModel.getObject().getFileAbsolutePath();
		InputStream is = new FileInputStream(path);

		// 1. Actual Data read from the Excel sheet
		fields = ExcelUtils.readExcelSheet(is, columns, startingRowIndex);

		final Form<Void> sform = new Form<Void>("ssform") {
			private static final long serialVersionUID = -4131257961358655262L;

			@Override
			protected void onSubmit() {
				processSpreadSheet(fields);
			}
		};

		// 2. render Header
		Loop headrow = new Loop("thead", columns) {
			private static final long serialVersionUID = -7173312633897220121L;

			@Override
			protected void populateItem(LoopItem item) {
				item.add(new Label("headttl", colTitles[item.getIteration()]));
			}

		};
		sform.add(headrow);

		// 3. Render Actual Data
		Loop rows = new Loop("rows", new PropertyModel<Integer>(this,
				"currentListSize")) {

			private static final long serialVersionUID = 6001997434713884740L;

			@Override
			protected void populateItem(LoopItem item) {
				final int rowNo = item.getIteration();
				item.add(new Label("sno", "" + (rowNo + 1)));
				final Form<Integer> innerForm = new Form<Integer>("iform",
						new Model<Integer>(rowNo));

				item.add(innerForm);
				innerForm.add(new Loop("cols", fields.get(rowNo).length) {

					private static final long serialVersionUID = 1769869465408991318L;

					@Override
					protected void populateItem(final LoopItem item1) {
						// item1.add(new TextField("data"));
						IModel<String> xcellModel = new IModel<String>() {

							private static final long serialVersionUID = 1065600741583659741L;

							public String getObject() {
								return fields.get(rowNo)[item1.getIteration()];
							}

							public void setObject(String object) {
								fields.get(rowNo)[item1.getIteration()] = object;
							}

							public void detach() {
							}

						};
						item1.add(new TextField<String>("data", xcellModel));
					}

				});

				// 4. render delete button
				innerForm.add(new SubmitLink("delRow") {

					private static final long serialVersionUID = 8010803692912722783L;

					@Override
					public void onSubmit() {
						int rem = innerForm.getModelObject();
						fields.remove(rem);
					}
				});
			}

		};
		add(sform);
		sform.add(rows);
		// Allow User to cancel the spreadsheet
		sform.add(new Link<Void>("cancelInput") {

			private static final long serialVersionUID = 2337638775008708180L;

			@Override
			public void onClick() {
				onCancel();
			}

		});
	}

	/**
	 * Completes incomplete header names
	 * 
	 * @param columnTitle
	 * @param columns
	 * @return
	 */
	private String[] createColumnTitle(String[] columnTitle, int columns) {
		String[] cttl = new String[columns];
		for (int i = 0; i < columns; i++) {
			if (i < columnTitle.length)
				cttl[i] = columnTitle[i];
			else
				cttl[i] = "Column #" + (i + 1);
		}
		return null;
	}

	/**
	 * Recreates complete header title
	 * 
	 * @param columns
	 * @return
	 */
	private String[] createColumnTitle(int columns) {
		String[] cttl = new String[columns];
		for (int i = 0; i < columns; i++) {
			cttl[i] = "Column #" + (i + 1);
		}
		return cttl;
	}

	public int getCurrentListSize() {
		return fields.size();
	}

	/**
	 * <p>
	 * User has accepted the input. You need to process and redirect to
	 * appropriate page, or leave on the page, if you want to show any message
	 * to correct the input.
	 * </p>
	 * 
	 */
	abstract protected void processSpreadSheet(List<String[]> fields);

	/**
	 * If user clicks cancel, take him to some other page, or do anything.
	 */
	abstract protected void onCancel();

}
